package com.china.bike.service.impl;

import com.alibaba.fastjson.JSON;
import com.china.bike.dao.BikeAccountDao;
import com.china.bike.dao.BikeInfoDao;
import com.china.bike.dto.BikeInfoVo;
import com.china.bike.dto.BikeListParam;
import com.china.bike.dto.PageBean;
import com.china.bike.entity.BikeAccount;
import com.china.bike.entity.BikeInfo;
import com.china.bike.entity.BikeUseRecord;
import com.china.bike.entity.User;
import com.china.bike.enums.BikeStatusEnum;
import com.china.bike.service.BikeInfoService;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.IntStream;

@Service
public class BikeInfoServiceImpl implements BikeInfoService {

    @Autowired
    private BikeInfoDao bikeInfoDao;
    @Autowired
    private BikeAccountDao bikeAccountDao;

    @Override
    public int saveBikeInfo(Integer bikeCount) {
        List<BikeInfo> bikeInfos = new ArrayList<>();
        IntStream.range(0, bikeCount).forEach(i -> {
            BikeInfo bikeInfo = new BikeInfo();
            bikeInfo.setBikeNum(String.valueOf(System.currentTimeMillis()) + (int) (Math.random() * 90 + 10));
            bikeInfo.setStorageDate(String.valueOf(new Date()));
            bikeInfo.setStatus(BikeStatusEnum.NORMAL.getCode());
            bikeInfos.add(bikeInfo);
        });
        return bikeInfoDao.saveBikeInfo(bikeInfos);
    }

    @Override
    public List<BikeInfoVo> listBikes(BikeListParam bikeListParam) {
        List<BikeInfo> bikeInfos = bikeInfoDao.listBikes(bikeListParam);
        List<Long> bikeIds = new ArrayList<>();
        List<BikeInfoVo> bikeInfoVos = new ArrayList<>();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (BikeInfo bikeInfo : bikeInfos) {
            BikeInfoVo bikeInfoVo = new BikeInfoVo();
            bikeInfoVo.setBikeId(bikeInfo.getBikeId());
            bikeInfoVo.setBikeNum(bikeInfo.getBikeNum());
            bikeInfoVo.setStatus(bikeInfo.getStatus());
            bikeInfoVo.setStorageDate(bikeInfo.getStorageDate().substring(0, bikeInfo.getStorageDate().length() - 2));
            bikeInfoVo.setBikeNum(bikeInfo.getBikeNum());
            bikeInfoVo.setRemark(bikeInfo.getRemark());
            bikeInfoVos.add(bikeInfoVo);
            bikeIds.add(bikeInfo.getBikeId());
        }
        if (bikeInfoVos != null && bikeInfoVos.size() > 0) {
            List<Map<String, String>> countByBikeIds = bikeInfoDao.getBikeUseRecordCountByBikeId(bikeIds);
            Map<String, Map<String, String>> mapHashMap = new HashMap<>();
            for (Map<String, String> countByBike : countByBikeIds) {
                System.out.println(JSON.toJSONString(countByBike));
                mapHashMap.put(String.valueOf(countByBike.get("bikeId")), countByBike);
            }
            System.out.println(JSON.toJSONString(mapHashMap));
            for (BikeInfoVo bikeInfoVo : bikeInfoVos) {
                System.out.println(bikeInfoVo.getBikeId());
                Map<String, String> map = mapHashMap.get(String.valueOf(bikeInfoVo.getBikeId()));
                if (map != null) {
                    bikeInfoVo.setUseCount(String.valueOf(map.get("useCount")));
                    bikeInfoVo.setLastUseTime(formatter.format(map.get("lastUseTime")));
                }
            }
        }
        return bikeInfoVos;
    }

    @Override
    public Integer listBikeCount(BikeListParam bikeListParam) {
        return bikeInfoDao.listBikeCount(bikeListParam);
    }

    /**
     * 开车
     *
     * @param bikeId
     * @param user
     */
    @Override
    public void driveBike(Long bikeId, User user) {
        BikeUseRecord bikeUseRecord = new BikeUseRecord();
        bikeUseRecord.setCreateTime(new Date());
        bikeUseRecord.setUserId(user.getId());
        bikeUseRecord.setBikeId(bikeId);
        bikeUseRecord.setBeginTime(new Date());
        bikeUseRecord.setUseType(1);

        bikeInfoDao.driveBike(bikeUseRecord);
    }

    /**
     * 锁车
     *
     * @param recordId
     * @param user
     */
    @Override
    public void lockBike(Long recordId, User user) {
        List<BikeUseRecord> bikeUseRecords = bikeInfoDao.getBikeByUserId(recordId, null, null);
        bikeUseRecords.stream().forEach(bikeUseRecord -> {
            Integer integer = calculateTime(bikeUseRecord.getBeginTime(), new Date());
            bikeUseRecord.setEndTime(new Date());
            bikeUseRecord.setUseTime(integer);
            //120分钟之内1元   之外2元
            BigDecimal useAmount = calculateAmount(integer);
            bikeUseRecord.setUseAmount(useAmount);
            bikeUseRecord.setUseType(2);
            bikeInfoDao.lockBike(bikeUseRecord);
            BikeAccount userAccount = bikeAccountDao.getUserAccount(bikeUseRecord.getUserId());
            BikeAccount bikeAccount = new BikeAccount();
            bikeAccount.setUserId(bikeUseRecord.getUserId());
            bikeAccount.setBalance(userAccount.getBalance().subtract(useAmount));
            bikeAccountDao.recordUseBike(bikeAccount);
        });
    }

    @Override
    public PageBean<BikeUseRecord> getBikeByUserId(Long userId, Integer start, Integer limit) {
        PageHelper.startPage(start, limit);
        List<BikeUseRecord> bikeUseRecords = bikeInfoDao.getBikeByUserId(userId, start, limit);
        int count = bikeInfoDao.getBikeByUserIdCount(userId);//总记录数
        PageBean<BikeUseRecord> pageData = new PageBean<>(start, limit, count);
        pageData.setRows(bikeUseRecords);
        return pageData;
    }

    @Override
    public int deleteBike(String bikeNum) {
        return bikeInfoDao.deleteBike(bikeNum);
    }

    @Override
    public int updateBikeStatus(BikeInfo bikeInfo) {
        return bikeInfoDao.updateBikeStatus(bikeInfo);
    }


    private Integer calculateTime(Date startDate, Date endDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;

        long diff = endDate.getTime() - startDate.getTime();
        long min = diff % nd % nh / nm;

        if (min == 0) {
            return 1;
        }
        return (int) min;
    }

    private BigDecimal calculateAmount(Integer useTime) {
        if (useTime < 120) {
            return new BigDecimal("1.00");
        }
        return new BigDecimal("2.00");
    }
}
